#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2020/5/28 11:30
# @Author  : yeungkhaichel
# @FileName: qy_base_case.py
# @Software: PyCharm

import time
import unittest
import uuid
import warnings

from ddt import  ddt,data

from base.qy_base_config import TEST_AUTH_URL, PROD_AUTH_URL, AUTH_TOKEN, FORM_DATA_HEADER
from base.runmethod import RunMethod
# from common.check import check_response_status
from common.logger import Logger
# from common.devices_sign import regist_sign, login_sign
from configs import config_manage
from data.hardware_data import InterfaceData
# from test_case.currency.test_currency import excel_data


class QyBaseCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        warnings.simplefilter('ignore', ResourceWarning)
        # 启动测试方法
        cls.run_method = RunMethod()
        pass

    @classmethod
    def tearDownClass(cls) -> None:
        pass

    def setUp(self) -> None:
        self.log = Logger(custom_color=True, name='qy_base_case')
        self.log.info("--------------------【{}测试用例开始】--------------------".format(self.__class__.__name__))

    def tearDown(self) -> None:
        self.log.info("--------------------【{}测试用例结束】--------------------\n".format(self.__class__.__name__))
        self.log.del_handler()  # 防止重复写入日志

    def base_assert(self, i, url, header, request_data, expect, res, data_case):
        """
        通用断言，根据预期结果键值对>断言>实际结果，相等则成功，反之失败
        :param i: 用例行
        :param url: 用例接口
        :param header: 请求头
        :param request_data: 请求数据
        :param expect: 预期结果
        :param res: 实际结果
        :param data_case: 用例
        :return: 是否成功标识
        """
        expect_keys = list(expect.keys())
        len_keys = len(expect_keys)

        global isSuccess

        for index, key in enumerate(expect_keys):
            # 最后键标识位
            if len_keys == index + 1:
                is_last = True
            else:
                is_last = False

            # 根据预期结果的键查询响应结果对应键，并断言
            if key in res.json().keys():
                e = type(res.json()[key])(expect[key])  # 转换expect值的type为result值的type
                try:
                    self.assertEqual(e, res.json()[key])
                except AssertionError:
                    self.log.info("请求接口: " + url)
                    self.log.info("请求头: " + str(header))
                    self.log.info("请求数据: " + str(request_data))
                    self.log.info("实际结果: " + res.text)
                    self.log.info("预期结果: " + str(expect))
                    data_case.write_result(i, res.text)
                    data_case.write_is_success(i, "Fail")
                    isSuccess = False
                    raise AssertionError(self.log.error("断言失败"))
                else:
                    if is_last is True:
                        self.log.info("请求接口: " + url)
                        self.log.info("请求头: " + str(header))
                        self.log.info("请求数据: " + str(request_data))
                        self.log.info("预期结果：" + str(expect))
                        self.log.info("实际结果：" + res.text)
                        self.log.info("断言成功")
                        data_case.write_result(i, res.text)
                        data_case.write_is_success(i, "Success")
                        isSuccess = True
            else:
                for k, v in res.json().items():
                    v_type = type(v)
                    while v_type != dict:
                        if v_type is list:
                            v_list = v
                            for vv in v_list:
                                if type(vv) is dict:
                                    v = vv
                                    v_type = dict
                        else:
                            break
                    else:
                        if key in v.keys():
                            e = type(v[key])(expect[key])  # 转换expect值的type为result值的type
                            try:
                                self.assertEqual(e, v[key])
                            except AssertionError:
                                self.log.info("请求接口: " + url)
                                self.log.info("请求头: " + str(header))
                                self.log.info("请求数据: " + str(request_data))
                                self.log.info("实际结果: " + res.text)
                                self.log.info("预期结果: " + str(expect))
                                data_case.write_result(i, res.text)
                                data_case.write_is_success(i, "Fail")
                                isSuccess = False
                                raise AssertionError(self.log.error("断言失败"))
                            else:
                                if is_last is True:
                                    self.log.info("请求接口: " + url)
                                    self.log.info("请求头: " + str(header))
                                    self.log.info("请求数据: " + str(request_data))
                                    self.log.info("预期结果：" + str(expect))
                                    self.log.info("实际结果：" + res.text)
                                    self.log.info("断言成功")
                                    data_case.write_result(i, res.text)
                                    data_case.write_is_success(i, "Success")
                                    isSuccess = True
        return isSuccess

    @staticmethod
    def get_keyValue(res, key):
        """
        根据键遍历查询请求结果，并返回键值
        :param res: 请求结果
        :param key: 结果中的某个键
        :return: 键值
        """
        if key in res.keys():
            return res[key]
        else:
            for k, v in res.items():
                v_type = type(v)
                while v_type != dict:
                    if v_type is list:
                        v_list = v
                        for vv in v_list:
                            if type(vv) is dict:
                                v = vv
                                v_type = dict
                    else:
                        break
                else:
                    if key in v.keys():
                        return v[key]

    def especcial_test(self):
        pass

    def auth_login(self, i, data_case, token_filename):
        """
        登录mpm，获取token等信息并存放token，以read_token()读token文件，用作全局变量，务必注意不要覆盖他人token文件路径
        :param i: excle表单的row num
        :param data_case: exlce中sheet的整页数据集合
        :param token_filename: 储存token的文件名
        :return:
        """
        self._testMethodDoc = data_case.get_title(i)  # 传入用例标题
        self.log.info("用例标题: " + self.shortDescription())  # shortDescription() 返回一行描述的测试结果信息

        is_run = data_case.get_is_run(i)  # 用例是否运行字段值为yes则返回True
        if is_run:
            global url
            env = data_case.get_env(i)
            method = data_case.get_request_method(i)  # 请求方法
            request_data = data_case.get_request_data(i)  # 请求数据
            expect = data_case.get_expect_data(i)  # 预期结果
            header = FORM_DATA_HEADER  # 请求头
            header['Authorization'] = AUTH_TOKEN
            header['host'] = 'auth-test.jifenzhi.info'
            if env == "prod":
                url = PROD_AUTH_URL + data_case.get_request_url(i)
                # header['host'] = 'auth.jifenzhi.info'
            else:
                url = TEST_AUTH_URL + data_case.get_request_url(i)  # 用例url
                # header['host'] = 'auth-test.jifenzhi.info'
            # sql_data = data_case.get_sql(i)  # 获取sql
            self.log.info("执行主用例".center(20, "*"))
            res = RunMethod().run_main(method=method, url=url, data=request_data, header=header)
            # return res.json()
            is_success = self.base_assert(i, url, header, request_data, expect, res, data_case)
            # 写入token到token.json文件
            if is_success is True:
                config_manage.assign_write_token(res.json(), token_filename)


if __name__ == '__main__':
    unittest.main()

